home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / machserver / 1.098 / proc / procFork.c < prev    next >
C/C++ Source or Header  |  1991-07-26  |  11KB  |  380 lines

  1. /* 
  2.  *  procFork.c --
  3.  *
  4.  *    Routines to create new processes.  No monitor routines are required
  5.  *    in this file.  Synchronization to proc table entries is by a call
  6.  *    to the proc table monitor to get a PCB and calls to the family monitor
  7.  *    to put a newly created process into a process family.
  8.  *
  9.  * Copyright (C) 1985, 1988 Regents of the University of California
  10.  * Permission to use, copy, modify, and distribute this
  11.  * software and its documentation for any purpose and without
  12.  * fee is hereby granted, provided that the above copyright
  13.  * notice appear in all copies.  The University of California
  14.  * makes no representations about the suitability of this
  15.  * software for any purpose.  It is provided "as is" without
  16.  * express or implied warranty.
  17.  */
  18.  
  19. #ifndef lint
  20. static char rcsid[] = "$Header: /sprite/src/kernel/proc/RCS/procFork.c,v 9.8 91/07/26 16:59:50 shirriff Exp $ SPRITE (Berkeley)";
  21. #endif /* not lint */
  22.  
  23. #include <sprite.h>
  24. #include <mach.h>
  25. #include <list.h>
  26. #include <proc.h>
  27. #include <procInt.h>
  28. #include <sched.h>
  29. #include <status.h>
  30. #include <stdlib.h>
  31. #include <string.h>
  32. #include <sync.h>
  33. #include <sys.h>
  34. #include <timer.h>
  35. #include <vm.h>
  36. #include <prof.h>
  37.  
  38. static ReturnStatus    InitUserProc _ARGS_((Proc_ControlBlock *procPtr,
  39.                 Proc_ControlBlock *parentProcPtr,
  40.                 Boolean shareHeap));
  41.  
  42.  
  43. /*
  44.  *----------------------------------------------------------------------
  45.  *
  46.  * Proc_Fork --
  47.  *
  48.  *    Process the fork system call.
  49.  *
  50.  * Results:
  51.  *    None.
  52.  *
  53.  * Side effects:
  54.  *    None.
  55.  *
  56.  *----------------------------------------------------------------------
  57.  */
  58.  
  59. int
  60. Proc_Fork(shareHeap, pidPtr)
  61.     Boolean    shareHeap;
  62.     Proc_PID    *pidPtr;
  63. {
  64.     Proc_PID        *newPidPtr;
  65.     int            numBytes;
  66.     ReturnStatus    status;
  67.     
  68.     /*
  69.      * Make the pointer to the process id that is to be returned accessible.
  70.      */
  71.  
  72.     Vm_MakeAccessible(VM_OVERWRITE_ACCESS, 
  73.               sizeof(Proc_PID), (Address) pidPtr,
  74.               &numBytes, (Address *) &newPidPtr);
  75.     if (numBytes < sizeof(Proc_PID)) {
  76.     return(SYS_ARG_NOACCESS);
  77.     }
  78.  
  79.     /*
  80.      * Start up the new process.  The PC where to begin execution doesn't 
  81.      * matter since it has already been stored in the proc table entry before
  82.      * we were called.
  83.      */
  84.  
  85.     status = Proc_NewProc((Address) 0, PROC_USER, shareHeap, newPidPtr,
  86.               (char *)NIL);
  87.  
  88.     Vm_MakeUnaccessible((Address) newPidPtr, numBytes);
  89.  
  90.     return(status);
  91. }
  92.  
  93.  
  94. /*
  95.  * ----------------------------------------------------------------------------
  96.  *
  97.  * Proc_NewProc --
  98.  *
  99.  *    Allocates a PCB and initializes it.
  100.  *
  101.  * Results:
  102.  *    Pointer to process control block for created process.
  103.  *
  104.  * Side effects:
  105.  *    PCB initialized and made runnable.
  106.  *
  107.  * ----------------------------------------------------------------------------
  108.  */
  109.  
  110. ReturnStatus
  111. Proc_NewProc(PC, procType, shareHeap, pidPtr, procName)
  112.     Address     PC;        /* The program counter where to start. */
  113.     int        procType;    /* One of PROC_KERNEL or PROC_USER. */
  114.     Boolean    shareHeap;    /* TRUE if share heap, FALSE if not. */
  115.     Proc_PID    *pidPtr;    /* A pointer to where to return the process
  116.                    ID in. */
  117.     char    *procName;    /* Name for process control block */
  118. {
  119.     ReturnStatus    status;
  120.     Proc_ControlBlock     *procPtr;    /* The new process being created */
  121.     Proc_ControlBlock     *parentProcPtr;    /* The parent of the new process,
  122.                      * the one that is making this call */
  123.     Boolean        migrated = FALSE;
  124.  
  125.     parentProcPtr = Proc_GetActualProc();
  126.  
  127.     if (parentProcPtr->genFlags & PROC_FOREIGN) {
  128.     migrated = TRUE;
  129.     }
  130.  
  131.     procPtr = ProcGetUnusedPCB();
  132.     if (pidPtr != (Proc_PID *) NIL) {
  133.     *pidPtr        = procPtr->processID;
  134.     }
  135.  
  136.     procPtr->Prof_Scale = 0;
  137.     Prof_Enable(procPtr, parentProcPtr->Prof_Buffer, 
  138.         parentProcPtr->Prof_BufferSize, parentProcPtr->Prof_Offset,
  139.     parentProcPtr->Prof_Scale);
  140.  
  141.     procPtr->processor        = parentProcPtr->processor;
  142.     procPtr->state         = PROC_READY;
  143.     procPtr->genFlags         = procType;
  144.     procPtr->syncFlags        = 0;
  145.     procPtr->schedFlags        = 0;
  146.     procPtr->exitFlags        = 0;
  147.  
  148.     if (!migrated) {
  149.     procPtr->parentID     = parentProcPtr->processID;
  150.     } else {
  151.     procPtr->parentID     = parentProcPtr->peerProcessID;
  152.     }
  153.     procPtr->familyID         = parentProcPtr->familyID;
  154.     procPtr->userID         = parentProcPtr->userID;
  155.     procPtr->effectiveUserID     = parentProcPtr->effectiveUserID;
  156.  
  157.     procPtr->billingRate     = parentProcPtr->billingRate;
  158.     procPtr->recentUsage     = 0;
  159.     procPtr->weightedUsage     = 0;
  160.     procPtr->unweightedUsage     = 0;
  161.  
  162.     procPtr->kernelCpuUsage.ticks     = timer_TicksZeroSeconds;
  163.     procPtr->userCpuUsage.ticks     = timer_TicksZeroSeconds;
  164.     procPtr->childKernelCpuUsage.ticks = timer_TicksZeroSeconds;
  165.     procPtr->childUserCpuUsage.ticks     = timer_TicksZeroSeconds;
  166.     procPtr->numQuantumEnds    = 0;
  167.     procPtr->numWaitEvents    = 0;
  168.     procPtr->event        = NIL;
  169.  
  170.     procPtr->kcallTable        = mach_NormalHandlers;
  171.     procPtr->unixProgress    = parentProcPtr->unixProgress;
  172.  
  173.     /* 
  174.      * Free up the old argument list, if any.  Note, this could be put
  175.      * in Proc_Exit, but is put here for consistency with the other
  176.      * reinitializations of control block fields.  
  177.      */
  178.  
  179.     if (procPtr->argString != (Address) NIL) {
  180.     free((Address) procPtr->argString);
  181.     procPtr->argString = (Address) NIL;
  182.     }
  183.  
  184.     /*
  185.      * Create the argument list for the child.  If no name specified, take
  186.      * the list from the parent.  If one is specified, just make a one-element
  187.      * list containing that name.
  188.      */
  189.     if (procName != (char *)NIL) {
  190.     procPtr->argString = (char *) malloc(strlen(procName) + 1);
  191.     (void) strcpy(procPtr->argString, procName);
  192.     } else if (parentProcPtr->argString != (Address) NIL) {
  193.     procPtr->argString =
  194.         (char *) malloc(strlen(parentProcPtr->argString) + 1);
  195.     (void) strcpy(procPtr->argString, parentProcPtr->argString);
  196.     }
  197.  
  198.     if (!migrated) {
  199.     if (ProcFamilyInsert(procPtr, procPtr->familyID) != SUCCESS) {
  200.         panic("Proc_NewProc: ProcFamilyInsert failed\n");
  201.     }
  202.     }
  203.  
  204.     /*
  205.      *  Initialize our child list to remove any old links.
  206.      *  If not migrated, insert this PCB entry into the list
  207.      *  of children of our parent.
  208.      */
  209.     List_Init((List_Links *) procPtr->childList);
  210.     if (!migrated) {
  211.     List_Insert((List_Links *) &(procPtr->siblingElement), 
  212.             LIST_ATREAR(parentProcPtr->childList));
  213.     }
  214.     Sig_Fork(parentProcPtr, procPtr);
  215.  
  216.     Vm_ProcInit(procPtr);
  217.  
  218.     /*
  219.      * If the process is migrated, setup its process state on the home node.
  220.      */
  221.     if (migrated) {
  222.     status = ProcRemoteFork(parentProcPtr, procPtr);
  223.     if (status != SUCCESS) {
  224.         /*
  225.          * We couldn't fork on the home node, so free up the new
  226.          * process that we were in the process of allocating.
  227.          */
  228.  
  229.         ProcFreePCB(procPtr);
  230.  
  231.         return(status);
  232.     }
  233.  
  234.     /*
  235.      * Change the returned process ID to be the process ID on the home
  236.      * node.
  237.      */
  238.     if (pidPtr != (Proc_PID *) NIL) {
  239.         *pidPtr = procPtr->peerProcessID;
  240.     }
  241.     } else {
  242.     procPtr->peerHostID = NIL;
  243.     procPtr->peerProcessID = NIL;
  244.     }
  245.  
  246.     /*
  247.      * Set up the virtual memory of the new process.
  248.      */
  249.  
  250.     if (procType == PROC_KERNEL) {
  251.     status = Mach_SetupNewState(procPtr, (Mach_State *)NIL,
  252.                     Sched_StartKernProc, PC, FALSE);
  253.     if (status != SUCCESS) {
  254.         /*
  255.          * We are out of kernel stacks.
  256.          */
  257.         ProcFreePCB(procPtr);
  258.         return(status);
  259.     }
  260.     } else {
  261.     status = InitUserProc(procPtr, parentProcPtr, shareHeap);
  262.     if (status != SUCCESS) {
  263.         /*
  264.          * We couldn't allocate virtual memory, so free up the new
  265.          * process that we were in the process of allocating.
  266.          */
  267.  
  268.         if (!migrated) {
  269.         ProcFamilyRemove(procPtr);
  270.         List_Remove((List_Links *) &(procPtr->siblingElement));
  271.         }
  272.         ProcFreePCB(procPtr);
  273.  
  274.         return(status);
  275.     }
  276.     }
  277.  
  278.     /*
  279.      * Set up the environment of the process.
  280.      */
  281.  
  282.     if (!migrated) {
  283.     ProcSetupEnviron(procPtr);
  284.     }
  285.     
  286.     /*
  287.      * Have the new process inherit filesystem state.
  288.      */
  289.     Fs_InheritState(parentProcPtr, procPtr);
  290.  
  291.     /*
  292.      * Return PROC_CHILD_PROC to the newly created process.
  293.      */
  294.     Mach_SetReturnVal(procPtr, (int) PROC_CHILD_PROC, 1);
  295.  
  296.     /*
  297.      * Put the process on the ready queue.
  298.      */
  299.     Sched_MakeReady(procPtr);
  300.  
  301.     return(SUCCESS);
  302. }
  303.  
  304.  
  305. /*
  306.  *----------------------------------------------------------------------
  307.  *
  308.  * InitUserProc --
  309.  *
  310.  *    Initalize the state for a user process.  This involves allocating
  311.  *    the segments for the new process.
  312.  *
  313.  * Results:
  314.  *    None.
  315.  *
  316.  * Side effects:
  317.  *    None.
  318.  *
  319.  *----------------------------------------------------------------------
  320.  */
  321.  
  322. static ReturnStatus
  323. InitUserProc(procPtr, parentProcPtr, shareHeap)
  324.     register    Proc_ControlBlock    *procPtr;    /* PCB to initialized.*/
  325.     register    Proc_ControlBlock    *parentProcPtr;    /* Parent's PCB. */
  326.     Boolean                shareHeap;    /* TRUE => share heap
  327.                              * with parent. */
  328. {
  329.     ReturnStatus    status;
  330.  
  331.     /*
  332.      * Set up a kernel stack for the process.
  333.      */
  334.     status = Mach_SetupNewState(procPtr, parentProcPtr->machStatePtr,
  335.                 Sched_StartUserProc, (Address)NIL, TRUE);
  336.     if (status != SUCCESS) {
  337.     return(status);
  338.     }
  339.  
  340.     /*
  341.      * Initialize all of the segments.  The system segment is the standard one.
  342.      * The code segment is the same as the parent process.  The stack segment
  343.      * is a copy of the parents.  Finally the heap segment is either a copy
  344.      * or the same as the parent depending on the share heap flag.
  345.      */
  346.  
  347.     procPtr->vmPtr->segPtrArray[VM_SYSTEM] = (Vm_Segment *) NIL;
  348.  
  349.     status = Vm_SegmentDup(parentProcPtr->vmPtr->segPtrArray[VM_STACK],
  350.             procPtr, &(procPtr->vmPtr->segPtrArray[VM_STACK]));
  351.     if (status != SUCCESS) {
  352.     Mach_FreeState(procPtr);
  353.     return(status);
  354.     }
  355.  
  356.     if (shareHeap) {
  357.     Vm_SegmentIncRef(parentProcPtr->vmPtr->segPtrArray[VM_HEAP], procPtr);
  358.     procPtr->vmPtr->segPtrArray[VM_HEAP] = 
  359.                 parentProcPtr->vmPtr->segPtrArray[VM_HEAP];
  360.     } else {
  361.     status = Vm_SegmentDup(parentProcPtr->vmPtr->segPtrArray[VM_HEAP],
  362.                procPtr, &(procPtr->vmPtr->segPtrArray[VM_HEAP]));
  363.     if (status != SUCCESS) {
  364.         Vm_SegmentDelete(procPtr->vmPtr->segPtrArray[VM_STACK], procPtr);
  365.         Mach_FreeState(procPtr);
  366.         return(status);
  367.     }
  368.     }
  369.  
  370.     if (parentProcPtr->vmPtr->sharedSegs != (List_Links *)NIL) {
  371.     Vm_CopySharedMem(parentProcPtr, procPtr);
  372.     }
  373.  
  374.     Vm_SegmentIncRef(parentProcPtr->vmPtr->segPtrArray[VM_CODE], procPtr);
  375.     procPtr->vmPtr->segPtrArray[VM_CODE] =
  376.                 parentProcPtr->vmPtr->segPtrArray[VM_CODE];
  377.  
  378.     return(SUCCESS);
  379. }
  380.